
package LFTrabalhoFinal;

import java.util.EmptyStackException;
import java.util.Locale;
import java.util.Stack;

/**Classe responsável pelo teste de aceitação ou não de uma cadeia.
 * Todo a cadeia é testada com base na linguagem L = {w | w não contém a subcadeia 000}
 * 
 * @author Euler Guimarães Lobo
 * @since Release R1 da aplicação
 * @version 1.0
 */
public class Automato {
       
    private Stack alfabeto = new Stack();
    private Stack alfabetoInvertido = new Stack();
    private int comprimento;
    private boolean rejeita = false;
    private boolean leitura = true;
    private char estado = '0';
    
    /**Inicializa com a cadeia solicitada para teste de aceitação.
     * 
     */
    public Automato(String palavra){
        
        palavra = palavra.toLowerCase(Locale.ENGLISH);        
        comprimento = palavra.length();
        
        for(int i = 1; i<=comprimento; i++){
            
            alfabetoInvertido.push(palavra.substring(i-1, i));
        }//Fim do laço for
        
        while(!alfabetoInvertido.empty()){
            
            alfabeto.push(alfabetoInvertido.pop());            
        }//Fim do laço while
        
        automatoAceitacao();
    }//Fim do Construtor

     private void automatoAceitacao(){
        
        while(leitura){
            
            switch(estado){
                case '0':
                    estadoQ0();
                    break;
                case '1':
                    estadoQ1();
                    break;
                case '2':
                    estadoQ2();
                    break;
            }//Fim do Swtich
        }//Fim do laço while        
    }//Fim do metodo automato

    private void estadoQ0(){
        
        Object atomico = "$";
        
        try{
            atomico = alfabeto.pop();
        }catch(EmptyStackException e){
            leitura = false;
            rejeita = false;
            return;
        }//Fim do laço try catch
        

        if(atomico.equals("0")){
            estado = '1';
        }else{
            if(atomico.equals("1")){
                estado = '0';
            }else{
                leitura = false;
                rejeita = true;
            }
        }//Fim do laço if
    }//Fim do metodo estadoQ0

    private void estadoQ1(){
        
        Object atomico = "$";
        
        try{
            atomico = alfabeto.pop();
        }catch(EmptyStackException e){
            leitura = false;
            rejeita = false;
            return;
        }//Fim do laço try catch
        
        if(atomico.equals("1")){
            estado = '0';
        }else{
            if(atomico.equals("0")){
                estado = '2';
            }else{
                leitura = false;
                rejeita = true;
            }
        }//Fim do laço if
    }//Fim do metodo estadoQ1

    private void estadoQ2(){
        
        Object atomico = "$";
        
        try{
            atomico = alfabeto.pop();
        }catch(EmptyStackException e){
            leitura = false;
            rejeita = false;
            return;
        }//Fim do laço try catch
        
        if(atomico.equals("1")){
            estado = '0';
        }//Fim do laço if
        else{
            leitura = false;
            rejeita = true;
        }//Fim do laço if        
    }//Fim do metodo estadoQ2
    
    /**
     * Retorno do valor lógico correspondente da cadeia, sendo o valor aceitável
     * pelo autômato (true) ou não (false)
     * @return Boolean - Se cadeia é aceitável ou não pelo autômato
     */
    public boolean getRejeita(){
        return rejeita;
    }//Fim do metodo getRejeita
    
    /**
     * Retorno do último estado alcançado pelo autômato.
     * Se a cadeia é correpondida somente por 1*, então o valor de retorno será 0;
     * para uma cadeia do tipo 1*0, o valor de retorno será 1
     * @return Char - estado final alcançado pelo autômato
     */
    public char getEstado(){
        return estado;
    }//Fim do metodo getEstado
}//Fim da Classe Automato
